{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "6eae5cf6",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sendgrid.helpers.mail import Mail, Email, To, Content\n",
    "import sendgrid\n",
    "import os\n",
    "from dotenv import load_dotenv\n",
    "from agents import Agent, Runner, trace, function_tool\n",
    "from pypdf import PdfReader\n",
    "from typing import Dict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "ed3d620b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "load_dotenv(override=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "a1de577d",
   "metadata": {},
   "outputs": [],
   "source": [
    "@function_tool\n",
    "def read_resume():\n",
    "    \"\"\" Read client's resume\"\"\"\n",
    "    resume_reader = PdfReader(\"me/Jongkook Kim - Resume.pdf\")\n",
    "    resume = \"\"\n",
    "    for page in resume_reader.pages:\n",
    "        page_text = page.extract_text()\n",
    "        if page_text:\n",
    "            resume += page_text.replace('\\t', ' ').replace('\\n', ' ')\n",
    "\n",
    "    return resume"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "f42eeae2",
   "metadata": {},
   "outputs": [],
   "source": [
    "resume_summary_instruction = \"\"\"You are a head hunter agent working for a client who is looking a job.\n",
    "Your client is a senior level sotware engineer and looking for principle or director level poisition.\n",
    "You summarize a client's resume includes technical skills, resposibilities and accomplishments.\n",
    "Summarized resume must compily follow requriements.\n",
    "1. Modern technical skills based on current job market and IT trends in year 2025.\n",
    "2. Qualfied for director or principle software engeering role.\n",
    "3. Summarized content should be 3 ~ 4 paragraphes\n",
    "\n",
    "##Resume\\n{resume}\\n\n",
    "\"\"\"\n",
    "\n",
    "resume_summarizor = Agent(\n",
    "    name=\"Resume Summarizor\",\n",
    "    instructions=resume_summary_instruction,\n",
    "    model=\"gpt-4o-mini\",\n",
    "    tools=[read_resume]\n",
    ")\n",
    "\n",
    "resume_summarize_tool = resume_summarizor.as_tool(\n",
    "    tool_name=\"resume_summarizor\",\n",
    "    tool_description=\"Summarize client resume to apeal HR or hiring manager\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "9a74d45b",
   "metadata": {},
   "outputs": [],
   "source": [
    "resume_summary_evaluator_instruction = \"\"\"\n",
    "You are a head hunter agent working for a client who is looking a job. \n",
    "Your role is evaluating summarized client's resume to meet following requriements.\n",
    "1. Modern technical skills based on current job market and IT trends in year 2025.\n",
    "2. Qualfied for director or principle software engeering role.\n",
    "3. Summarized content should be 3 ~ 4 paragraphes\n",
    "\n",
    "If the summarized resume doesn't meet the requrements, give feedback why it fails the evaluation, \n",
    "so resume_summarize_tool can summarize again using your feedback.\n",
    "\"\"\"\n",
    "\n",
    "resume_summary_evaluator = Agent(\n",
    "    name=\"Summarized Resume Evaluator\",\n",
    "    instructions=resume_summary_evaluator_instruction,\n",
    "    tools=[read_resume],\n",
    "    model=\"gpt-4o-mini\"\n",
    ")\n",
    "\n",
    "resume_summary_evaluator_tool = resume_summary_evaluator.as_tool(\n",
    "    tool_name=\"resume_summary_evaluator\",\n",
    "    tool_description=\"Evaluate summerized resume\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "329e3182",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "@function_tool\n",
    "def send_email(subject: str, body: str) -> Dict[str, str]:\n",
    "    \"\"\" Send out an email with given subject and body to all HR or hiring managers\"\"\"\n",
    "    sg = sendgrid.SendGridAPIClient(api_key=os.getenv(\"SENDGRID_API_KEY\"))\n",
    "    from_email = Email(\"gaulbi@gmail.com\")\n",
    "    to_email = To(\"gaulbi@gmail.com\")\n",
    "    content = Content(\"text/plain\", body)\n",
    "    mail = Mail(from_email=from_email, to_emails=to_email, subject=subject, plain_text_content=content).get()\n",
    "    response = sg.client.mail.send.post(request_body=mail)\n",
    "    \n",
    "    return {\"status\": response.status_code}\n",
    "\n",
    "create_email_instruction = \"\"\"You are a head hunter agent working for a client who is looking a job.\n",
    "Your client is a senior level sotware engineer and looking for principle or director level poisition.\n",
    "You write professional, serious cold emails based on summarized client's resume.\n",
    "Explanation of the client professional experience in email should be accurate and appeals to HR or hiring manager. \n",
    "\n",
    "##Resume\\n{resume}\\n\n",
    "\"\"\"\n",
    "\n",
    "email_sendor = Agent(\n",
    "    name=\"Email Generator\",\n",
    "    instructions=create_email_instruction,\n",
    "    model=\"gpt-4o-mini\",\n",
    "    tools=[send_email]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "3a877b61",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Agent(name='Head Hunter Manager', instructions=\"\\nYou are a Job Head Hunter Manager. \\nYour goal is \\n- find the single best summerized client resume using resume_summarizor tool,\\n- generate a email subject baesd on the summarized resume \\n- the single best email using send_email tool.\\n\\nFollow these steps carefully:\\n1. Summarize client resume: Use resume_summarizor tool to summarize client's resume.\\n2. Evaluate and Select: Use resume_summary_evaluator_tool tool to evaluate the summarized resume. If it dosen't pass the evaluation, call resume_summarizor tool to summarize again. Repeat summary - evaluation steps upto 3 times, if the summary keeps failing the evaluation. If it fails in 3 times, you choose the best one in the 3 summarized resumes.\\n3. Generate Email Subject: Generate the email subject using the best version of resume summary. Subject shouldn't exceed 50 characters. \\n4. Pass Summarized Resume and Email Subject to send_email tool, so send_email tool can inject the subject into the email subject and use summarized resume to generate email body.\\n4. Hands off to send_email agent only summarizing resume by resume_summarizor, evaluating by resume_summary_evaluator_tool tool and creating summary by you are completed. \\nPass Summarized Resume and Email Subject to send_email agent, so send_email agent can inject the subject into the email subject and use summarized resume to generate email body.\\n\\nCurcial Rules:\\n- You must use the resume_summarizor tool to summarize client's resume - do not write it yourself.\\n\", prompt=None, handoff_description=None, handoffs=[Agent(name='Email Generator', instructions=\"You are a head hunter agent working for a client who is looking a job.\\nYour client is a senior level sotware engineer and looking for principle or director level poisition.\\nYou write professional, serious cold emails based on summarized client's resume.\\nExplanation of the client professional experience in email should be accurate and appeals to HR or hiring manager. \\n\\n##Resume\\n{resume}\\n\\n\", prompt=None, handoff_description=None, handoffs=[], model='gpt-4o-mini', model_settings=ModelSettings(temperature=None, top_p=None, frequency_penalty=None, presence_penalty=None, tool_choice=None, parallel_tool_calls=None, truncation=None, max_tokens=None, reasoning=None, metadata=None, store=None, include_usage=None, extra_query=None, extra_body=None, extra_headers=None, extra_args=None), tools=[FunctionTool(name='send_email', description='Send out an email with given subject and body to all HR or hiring managers', params_json_schema={'properties': {'subject': {'title': 'Subject', 'type': 'string'}, 'body': {'title': 'Body', 'type': 'string'}}, 'required': ['subject', 'body'], 'title': 'send_email_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x123b39c60>, strict_json_schema=True, is_enabled=True)], mcp_servers=[], mcp_config={}, input_guardrails=[], output_guardrails=[], output_type=None, hooks=None, tool_use_behavior='run_llm_again', reset_tool_choice=True)], model='gpt-4o-mini', model_settings=ModelSettings(temperature=None, top_p=None, frequency_penalty=None, presence_penalty=None, tool_choice=None, parallel_tool_calls=None, truncation=None, max_tokens=None, reasoning=None, metadata=None, store=None, include_usage=None, extra_query=None, extra_body=None, extra_headers=None, extra_args=None), tools=[FunctionTool(name='resume_summarizor', description='Summarize client resume to apeal HR or hiring manager', params_json_schema={'properties': {'input': {'title': 'Input', 'type': 'string'}}, 'required': ['input'], 'title': 'resume_summarizor_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x121ed6de0>, strict_json_schema=True, is_enabled=True), FunctionTool(name='resume_summary_evaluator', description='Evaluate summerized resume', params_json_schema={'properties': {'input': {'title': 'Input', 'type': 'string'}}, 'required': ['input'], 'title': 'resume_summary_evaluator_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x1237920c0>, strict_json_schema=True, is_enabled=True)], mcp_servers=[], mcp_config={}, input_guardrails=[], output_guardrails=[], output_type=None, hooks=None, tool_use_behavior='run_llm_again', reset_tool_choice=True)\n"
     ]
    }
   ],
   "source": [
    "head_hunter_manager_instruction = \"\"\"\n",
    "You are a Job Head Hunter Manager. \n",
    "Your goal is \n",
    "- find the single best summerized client resume using resume_summarizor tool,\n",
    "- generate a email subject baesd on the summarized resume \n",
    "- the single best email using send_email tool.\n",
    "\n",
    "Follow these steps carefully:\n",
    "1. Summarize client resume: Use resume_summarizor tool to summarize client's resume.\n",
    "2. Evaluate and Select: Use resume_summary_evaluator_tool tool to evaluate the summarized resume. If it dosen't pass the evaluation, call resume_summarizor tool to summarize again. Repeat summary - evaluation steps upto 3 times, if the summary keeps failing the evaluation. If it fails in 3 times, you choose the best one in the 3 summarized resumes.\n",
    "3. Generate Email Subject: Generate the email subject using the best version of resume summary. Subject shouldn't exceed 50 characters. \n",
    "4. Pass Summarized Resume and Email Subject to send_email tool, so send_email tool can inject the subject into the email subject and use summarized resume to generate email body.\n",
    "4. Hands off to send_email agent only summarizing resume by resume_summarizor, evaluating by resume_summary_evaluator_tool tool and creating summary by you are completed. \n",
    "Pass Summarized Resume and Email Subject to send_email agent, so send_email agent can inject the subject into the email subject and use summarized resume to generate email body.\n",
    "\n",
    "Curcial Rules:\n",
    "- You must use the resume_summarizor tool to summarize client's resume - do not write it yourself.\n",
    "\"\"\"\n",
    "\n",
    "head_hunter_manager = Agent(\n",
    "    name=\"Head Hunter Manager\",\n",
    "    instructions=head_hunter_manager_instruction,\n",
    "    tools=[resume_summarize_tool, resume_summary_evaluator_tool],\n",
    "    model=\"gpt-4o-mini\",\n",
    "    handoffs=[email_sendor]\n",
    ")\n",
    "\n",
    "print(head_hunter_manager)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a7a9b0f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "message = \"Summarize client resume and send email \"\n",
    "with trace(\"Automated Job Head Hunter\"):\n",
    "    result = await Runner.run(head_hunter_manager, message)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
